<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>视频卡顿</title>
</head>

<body>
  <div class="example">
    <button type="button">Load video</button>
    <video controls width="250"></video>

    <div class="event-log">
      <label>Event log:</label>
      <textarea readonly class="event-log-contents"></textarea>
    </div>
  </div>

  <script type="text/javascript">
    const loadVideo = document.querySelector("button");
    const video = document.querySelector("video");
    const eventLog = document.querySelector(".event-log-contents");
    let source = null;

    var videoDuration = 23 * 1000; // 单位秒s, 整数类型

    var actualVideoDuration = 0.0; // 单位秒s

    var startPlayTime = 0; // 开始播放时间戳
    var endPlayTime = 0; // 结束播放时间戳
    var playDuration = 0; // 视频持续播放时长（含缓冲、提前结束），结束/停止播放事件时间 - 开始播放时间
    var actualPlayDuration = 0; // 时间播放进度时长：取视频结束/停止播放时的视频进度时间
    var errorNo = ''
    var errorMessage = ''

    function handleEvent(event) {
      // 开始计时
      if (event.type === 'loadstart') {
        startPlayTime = Date.now();
      }
      // video标签的时间
      if (event.type === 'loadedmetadata') {
        actualVideoDuration = event.target.duration * 1000;
      }
      // 实际播放进度时间（视频时时长进度）
      if (event.type === 'timeupdate') {
        actualPlayDuration = event.target.currentTime * 1000;
      }
      // 当用户代理尝试获取媒体数据但数据意外未获取时，会发生该事件
      if (event.type === 'stalled') {
        // console.error(event);
        errorNo = -30001;
        errorMessage = error?.message || '数据获取失败，但在重试.';
      }
      // 时间的播放时间
      if (['ended', 'error'].includes(event.type)) {
        if (event.type === 'error') {
          errorNo = -30002;
          errorMessage = error?.message || '视频播放失败.';
        }
        endPlayTime = Date.now();
        playDuration = endPlayTime - startPlayTime;
        console.table([
          ['视频时长（整数）s', '视频真实时长(精度)s', '播放用时s', '实际播放进度s', '错误原因'],
          [videoDuration, actualVideoDuration, playDuration, actualPlayDuration, event?.message]
        ])
      }
      eventLog.textContent = eventLog.textContent + `【${event.type}】\n长度：${event.target.duration}\n时长：${event.target.currentTime}\n`;
    }

    video.addEventListener("loadstart", handleEvent);
    video.addEventListener("loadedmetadata", handleEvent);
    video.addEventListener("stalled", handleEvent); // 当用户代理尝试获取媒体数据但数据意外未获取时，会发生该事件
    // video.addEventListener("progress", handleEvent);
    video.addEventListener("waiting", handleEvent);
    video.addEventListener("timeupdate", handleEvent);
    video.addEventListener("error", handleEvent);
    video.addEventListener("ended", handleEvent);
    video.addEventListener("canplay", handleEvent);
    video.addEventListener("canplaythrough", handleEvent);

    loadVideo.addEventListener("click", () => {
      startPlayTime = Date.now();
      if (source) {
        document.location.reload();
      } else {
        loadVideo.textContent = "Reset example";
        source = document.createElement("source");
        source.setAttribute(
          "src",
          "https://vodhbspeed.duomian-static.com/sv/1d2b3968-1912bb9d242/1d2b3968-1912bb9d242.mp4"
          // "https://mdn.github.io/learning-area/html/multimedia-and-embedding/video-and-audio-content/rabbit320.mp4",
        );
        source.setAttribute("type", "video/mp4");

        video.appendChild(source);
      }
    });

  </script>
</body>

</html>